$(function(){

    var _canvas,_engine,_scene,_camera;
    var _projects,_selectedBuilding,_selectedFloor,_stationMap;
    var _projecttion = Utils.Gauss_Krueger_Projection(4490,114);
    var _beaconServiceRunning = false;
    var _getBeaconInterval;

    function init()
    {
        _canvas = document.getElementById('renderCanvas');
        _engine = new BABYLON.Engine(_canvas, true);
        
        _scene = createScene();
        //TODO:删除
        window.__scene = _scene;
        _engine.runRenderLoop(function() {
            if (_scene.activeCamera) {
                _scene.render();
            }
        });

        initEvent();

        showAxis(100)

        loadProjects();

        loadHuman();
    }

    function initEvent()
    {
        $(window).on('resize',function(){
            _engine.resize();
        })

        $('#project_select').on('change',function(){
            const project = _projects[$('#project_select').val()]
            showBuildings(project);
        })

        _scene.onPointerObservable.add((info) => {
            switch (info.type) {
                case BABYLON.PointerEventTypes.POINTERTAP:
                    if (!info.pickInfo.pickedMesh) {
                        clearFloors();
                    }
                break;
                case BABYLON.PointerEventTypes.POINTERPICK:
                    const pickMesh = info.pickInfo.pickedMesh;
                    const rootMesh = getRootMesh(pickMesh);
                    if (rootMesh.id.startsWith('building_')) {
                        var buildingId = rootMesh.id.replace('building_','').replace('_root','')
                        var branches = getBranches(rootMesh);
                        branches.forEach(branch => {
                            branch.visibility = 0.3;
                        });
                        showFloors(buildingId)
                    }
                    break;
            
                default:
                    break;
            }
        });

        $('#btn_test').on('click',function(){
            if (cordova && cordova.plugins && cordova.plugins.Beacon) {
                if (!_beaconServiceRunning) {
                    if (cordova.plugins.Beacon.startService) {
                        cordova.plugins.Beacon.startService(function(result)
                        {
                            _beaconServiceRunning = true;
                            _getBeaconInterval = setInterval(() => {
                                getBeacons();
                            }, 1000);
                            $('#btn_test').text('停止');
                        });
                    }
                }
                else
                {
                    if (cordova.plugins.Beacon.stopService) {
                        cordova.plugins.Beacon.stopService(function(result)
                        {
                            clearInterval(_getBeaconInterval)
                            _beaconServiceRunning = false;
                            $('#btn_test').text('开启');
                        });
                    }
                }
                
            }
        });
    }
    


    const createScene = function() {
        const scene = new BABYLON.Scene(_engine);
        _camera = new BABYLON.ArcRotateCamera('camera', -Math.PI/2, 0, 300, new BABYLON.Vector3(0, 0, 0));
        _camera.inputs.attached.mousewheel.wheelPrecision = 2;
        _camera.inputs.attached.pointers.panningSensibility = 25;
        _camera.attachControl(_canvas, true);
        //TODO:删除
        window.__camera = _camera;
        const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0));
        return scene;
    }

    var showAxis = function (size) {
        var makeTextPlane = function (text, color, size) {
            var dynamicTexture = new BABYLON.DynamicTexture('DynamicTexture', 50, _scene, true);
            dynamicTexture.hasAlpha = true;
            dynamicTexture.drawText(text, 5, 40, 'bold 36px Arial', color, 'transparent', true);
            var plane = new BABYLON.Mesh.CreatePlane('TextPlane', size, _scene, true);
            plane.material = new BABYLON.StandardMaterial('TextPlaneMaterial', _scene);
            plane.material.backFaceCulling = false;
            plane.material.specularColor = new BABYLON.Color3(0, 0, 0);
            plane.material.diffuseTexture = dynamicTexture;
            return plane;
        };

        var axisX = BABYLON.Mesh.CreateLines('axisX', [
            new BABYLON.Vector3.Zero(), new BABYLON.Vector3(size, 0, 0), new BABYLON.Vector3(size * 0.95, 0.05 * size, 0),
            new BABYLON.Vector3(size, 0, 0), new BABYLON.Vector3(size * 0.95, -0.05 * size, 0)
        ], _scene);
        axisX.color = new BABYLON.Color3(1, 0, 0);
        var xChar = makeTextPlane('X', 'red', size / 10);
        xChar.position = new BABYLON.Vector3(0.9 * size, -0.05 * size, 0);
        var axisY = BABYLON.Mesh.CreateLines('axisY', [
            new BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, size, 0), new BABYLON.Vector3(-0.05 * size, size * 0.95, 0),
            new BABYLON.Vector3(0, size, 0), new BABYLON.Vector3(0.05 * size, size * 0.95, 0)
        ], _scene);
        axisY.color = new BABYLON.Color3(0, 1, 0);
        var yChar = makeTextPlane('Y', 'green', size / 10);
        yChar.position = new BABYLON.Vector3(0, 0.9 * size, -0.05 * size);
        var axisZ = BABYLON.Mesh.CreateLines('axisZ', [
            new BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, 0, size), new BABYLON.Vector3(0, -0.05 * size, size * 0.95),
            new BABYLON.Vector3(0, 0, size), new BABYLON.Vector3(0, 0.05 * size, size * 0.95)
        ], _scene);
        axisZ.color = new BABYLON.Color3(0, 0, 1);
        var zChar = makeTextPlane('Z', 'blue', size / 10);
        zChar.position = new BABYLON.Vector3(0, 0.05 * size, 0.9 * size);
    };

    /************************
     * 加载所有项目数据
     ************************/
     function loadProjects() {
        $('#project_select').empty();
        $.post(`${Config.BASE_URL}/api/project/list-all`, JSON.stringify({}), function (response) {
            if (response.succeeded) {
                _projects = response.data;
                for (let index = 0; index < _projects.length; index++) {
                    const project = _projects[index];
                    $('#project_select').append(`<option value=${index}>${project.name}</option>`)
                }
                if (_projects.length > 0) {
                    showBuildings(_projects[0]);
                }
            }
        })
    }

    var _minx = 9999999999,_miny = 9999999999;
    /**
     * 展示建筑物
     * @param {*} project 
     */
    function showBuildings(project){
        _scene.meshes.forEach(mesh => {
            if (mesh.id.startsWith('building_')) {
                _scene.removeMesh(mesh,true);
            }
        });
        const buildings = project.buildings;
        //获取最小XY当零点
        _minx = 9999999999,_miny = 9999999999
        for (let index = 0; index < buildings.length; index++) {
            const building = buildings[index];
            var position = _projecttion.LngLat2XY(building.x,building.y);
            if (position[0] < _minx) {
                _minx = position[0];
            }
            if (position[1] < _miny) {
                _miny = position[1];
            }
        }
        buildings.forEach(building => {
            BABYLON.SceneLoader.LoadAssetContainer(`${Config.BASE_URL}/api/building/download-model/`, building.model, _scene, function (container) {
                container.meshes[0].id = `building_${building.id}_root`;
                container.meshes[0].name = `building_${building.id}_root`;
                var position = calRelativePosition(building.x,building.y);
                container.meshes[0].position = new BABYLON.Vector3(position[0], 0, position[1]);
                //为了符合Cesium坐标系，有转过方向，得转回来
                container.meshes[0].rotation = new BABYLON.Vector3(0, -Math.PI/2, 0);
                container.addAllToScene();
            });
        });
        
    }

    /**
         * 展示一个建筑物的楼层
         * @param {*} buildingId 
         */
     function showFloors(buildingId) {
        $('#lg_floor').empty();
        $.get(`${Config.BASE_URL}/api/building/${buildingId}`, function (response) {
            if (response.succeeded) {
                _selectedBuilding = response.data;
                for (let index = 0; index < _selectedBuilding.floors.length; index++) {
                    const floor = _selectedBuilding.floors[index];
                    $('#lg_floor').append(`<a href="javascript: void(0);" class="list-group-item list-group-item-action">${floor.name}</a>`);
                }
                $('#lg_floor').fadeIn();
                $('#lg_floor .list-group-item').on('click', function (e) {
                    const index = $(e.target).index();
                    showFloor(index);
                })
                if (_selectedBuilding.floors.length > 0) {
                    showFloor(0)
                }
            }
        })
    }

    /**
         * 展示单个图层
         * @param {*} index 
         */
     function showFloor(index) {
        _scene.meshes.forEach(mesh => {
            if (mesh.id.startsWith('floor_')) {
                _scene.removeMesh(mesh,true);
            }
        });
        $('#lg_floor .list-group-item').removeClass('active');
        $(`#lg_floor .list-group-item:nth-child(${index + 1})`).addClass('active')
        _selectedFloor = _selectedBuilding.floors[index];
        loadStations(_selectedFloor.id);
        BABYLON.SceneLoader.LoadAssetContainer(`${Config.BASE_URL}/api/floor/download-model/`, _selectedFloor.model, _scene, function (container) {
            container.meshes[0].id = `floor_${_selectedFloor.id}_root`;
            container.meshes[0].name = `floor_${_selectedFloor.id}_root`;
            var position = calRelativePosition(_selectedFloor.x,_selectedFloor.y)
            container.meshes[0].position = new BABYLON.Vector3(position[0], _selectedFloor.height, position[1]);
            //为了符合Cesium坐标系，有转过方向，得转回来
            container.meshes[0].rotation = new BABYLON.Vector3(0, -Math.PI/2, 0);
            container.addAllToScene();
        });
        //showStations(floor);
    }

    /**
         * 清除建筑物图层
         */
     function clearFloors() {
        $('#lg_floor').fadeOut();
        _scene.meshes.forEach(mesh => {
            if (mesh.visibility == 0.3) {
                mesh.visibility = 1;
            }
            if (mesh.id.startsWith('floor_')) {
                _scene.removeMesh(mesh,true);
            }
        });
    }

    function loadHuman()
    {
        BABYLON.SceneLoader.LoadAssetContainer('./','data/man.glb' , _scene, function (container) {
            container.meshes[0].id = '__human__';
            container.meshes[0].name = '__human__';
            container.addAllToScene();
        });
    }

    /**
     * 获取根节点
     * @param {*} mesh 
     * @returns 
     */
    function getRootMesh(mesh)
    {
        if (mesh._parentNode) {
            return getRootMesh(mesh._parentNode)
        }
        else
        {
            return mesh;
        }
    }

    /**
     * 获取分支节点
     * @param {*} mesh 
     */
    function getBranches(mesh)
    {
        var children = [];
        if (mesh._children) {
            mesh._children.forEach(child => {
                children = children.concat(getBranches(child));
            });
        }
        else
        {
            children.push(mesh);
        }
        return children;
    }

    /**
     * 获取该项目的所有基站
     */
    function loadStations(floorId) {
        $.get(`${Config.BASE_URL}/api/station/list-by-floor/${floorId}`, function (response) {
            _stationMap = {};
            response.data.forEach(station => {
                _stationMap[station.uuid] = station;
            });
            console.log(_stationMap);
        });
    }

    /**
     * 获取Beacon设备
     */
    function getBeacons()
    {
        if (cordova && cordova.plugins && cordova.plugins.Beacon)
        {
            if (cordova.plugins.Beacon.getBeacons) {
                cordova.plugins.Beacon.getBeacons(function(beacons){
                    var sortBeacons = beacons.sort(function(a,b){
                        return b.rssi - a.rssi;
                    })
                    var text = '';
                    sortBeacons.forEach(beacon => {
                        //选择信号最强的三个
                        text += `<p>UUID:${beacon.uuid.substring(24).toUpperCase()}</p>`
                        var measuredPower = -59;
                        if (_stationMap && _stationMap[beacon.uuid.toUpperCase()]) {
                            measuredPower = _stationMap[beacon.uuid.toUpperCase()].measuredPower;
                        }
                        text += `<p>信号:${measuredPower - beacon.rssi}dBm</p>`
                        //text += `<p>数据:${beacon.major.toString()}/${beacon.minor.toString()}</p>`
                    });
                    $('#div_info').html(text);
                    if (sortBeacons.length >= 3) {
                        setHumanLocation(sortBeacons);
                    }
                })
            }
        }
    }

    /**
     * 设置人的位置
     * @param {*} beacons 
     * @returns 
     */
    function setHumanLocation(beacons) {
        const triangle = _scene.getMeshByID('station_triangle');
        if (triangle) {
            _scene.removeMesh(triangle,true);
        }

        const beacon1 = beacons[0];
        const beacon2 = beacons[1];
        const beacon3 = beacons[2];
        if (!_stationMap) {
            return;
        }
        const station1 = _stationMap[beacon1.uuid.toUpperCase()];
        const station2 = _stationMap[beacon2.uuid.toUpperCase()];
        const station3 = _stationMap[beacon3.uuid.toUpperCase()];
        if (!station1 || !station2 || !station3) {
            console.log('基站信息未获取');
            return;
        }

        const station1Postion = calRelativePosition(station1.position.x,station1.position.y);
        const station2Postion = calRelativePosition(station2.position.x,station2.position.y);
        const station3Postion = calRelativePosition(station3.position.x,station3.position.y);

        let triangleHeight = 1;
        if (_selectedFloor) {
            triangleHeight = _selectedFloor.height + 1;
        }
        const positons = [
            new BABYLON.Vector3(station1Postion[0], triangleHeight, station1Postion[1]),
            new BABYLON.Vector3(station2Postion[0], triangleHeight, station2Postion[1]),
            new BABYLON.Vector3(station3Postion[0], triangleHeight, station3Postion[1]),
            new BABYLON.Vector3(station1Postion[0], triangleHeight, station1Postion[1]),
        ]

        const stationTriangle = BABYLON.MeshBuilder.CreateLines('station_triangle', {points: positons});

        let decay1 =  station1.measuredPower - beacon1.rssi;
        let decay2 =  station2.measuredPower - beacon2.rssi;
        let decay3 =  station3.measuredPower - beacon3.rssi;
        decay1 = decay1>0?decay1:1;
        decay2 = decay2>0?decay2:1;
        decay3 = decay3>0?decay3:1;

        const distanceOption = {units: 'kilometers'};
        const length12 = turf.distance(turf.point(station1Postion),turf.point(station2Postion),distanceOption);
        const length23 = turf.distance(turf.point(station2Postion),turf.point(station3Postion),distanceOption);
        const length13 = turf.distance(turf.point(station1Postion),turf.point(station3Postion),distanceOption);

        const line12 = turf.lineString([station1Postion,station2Postion]);
        const line23 = turf.lineString([station2Postion,station3Postion]);
        const line13 = turf.lineString([station1Postion,station3Postion]);

        // const point12 = turf.along(line12, length12 * power1 * power1/(power1 * power1 + power2 * power2), distanceOption);
        // const point23 = turf.along(line23, length23 * power2 * power2/(power2 * power2 + power3 * power3), distanceOption);
        // const point13 = turf.along(line13, length13 * power1 * power1/(power1 * power1 + power3 * power3), distanceOption);
        const point12 = turf.along(line12, length12 * decay1/(decay1 + decay2), distanceOption);
        const point23 = turf.along(line23, length23 * decay2/(decay2 + decay3), distanceOption);
        const point13 = turf.along(line13, length13 * decay1/(decay1 + decay3), distanceOption);

        const features = turf.polygon([
            [
                point12.geometry.coordinates,
                point23.geometry.coordinates,
                point13.geometry.coordinates,
                point12.geometry.coordinates]
        ]);
        const center = turf.centerOfMass(features);
        const centerX = center.geometry.coordinates[0];
        const centerY = center.geometry.coordinates[1];

        const mesh = _scene.getMeshByID('__human__');
        if (mesh) {
            let height = 0;
            if (_selectedFloor) {
                height = _selectedFloor.height + 0.24;
            }
            mesh.position = new BABYLON.Vector3(centerX, height, centerY);
        }
    }

    /**
     * 计算相对坐标
     * @param {*} lng 
     * @param {*} lat 
     */
    function calRelativePosition(lng,lat) {
        var position = _projecttion.LngLat2XY(lng,lat);
        position[0] = position[0] - _minx;
        position[1] = position[1] - _miny;
        return position;
    }
    

    init();
    
    window.App = {
        /**
         * 设置人的位置
         * @param {*} longitude 
         * @param {*} latitude 
         */
        setPosition:function(longitude,latitude)
        {
            var mesh = _scene.getMeshByID('__human__');
            if (mesh) {
                var position = _projecttion.LngLat2XY(longitude,latitude);
                var height = 0;
                if (_selectedFloor) {
                    height = _selectedFloor.height + 0.24;
                }
                mesh.position = new BABYLON.Vector3(position[0] - _minx, height, position[1] - _miny);
            }
            
        }
    }
})